#include "usb2uart.h"

#define usart_buffer_size 1024
uint8_t usart_rx_buffer[usart_buffer_size];

void uartx_preinit(void)
{
  gpio_init_type gpio_init_struct;

  crm_periph_clock_enable(CRM_USART2_PERIPH_CLOCK, TRUE);
  crm_periph_clock_enable(CRM_GPIOA_PERIPH_CLOCK, TRUE);

  gpio_default_para_init(&gpio_init_struct);
  gpio_init_struct.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
  gpio_init_struct.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
  gpio_init_struct.gpio_mode = GPIO_MODE_MUX;
  gpio_init_struct.gpio_pull = GPIO_PULL_NONE;
  /* configure the usart2 tx pin */
  gpio_init_struct.gpio_pins = GPIO_PINS_2;
  gpio_init(GPIOA, &gpio_init_struct);
  /* configure the usart2 rx pin */
  gpio_init_struct.gpio_pull = GPIO_PULL_UP;
  gpio_init_struct.gpio_pins = GPIO_PINS_3;
  gpio_init(GPIOA, &gpio_init_struct);

  gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE2, GPIO_MUX_1);
  gpio_pin_mux_config(GPIOA, GPIO_PINS_SOURCE3, GPIO_MUX_1);

  //  nvic_irq_enable(USART2_IRQn, 0, 0);

  /* configure usart3 param */
  usart_init(USART2, 115200, USART_DATA_8BITS, USART_STOP_1_BIT);
  usart_transmitter_enable(USART2, TRUE);
  usart_receiver_enable(USART2, TRUE);
  //  usart_dma_transmitter_enable(USART2, TRUE);
  usart_dma_receiver_enable(USART2, TRUE);

  //  usart_interrupt_enable(USART3, USART_RDBF_INT, FALSE);
  usart_enable(USART2, TRUE);

  dma_init_type dma_init_struct;
  /* enable dma1 clock */
  crm_periph_clock_enable(CRM_DMA1_PERIPH_CLOCK, TRUE);
  /* dma1 channel3 for usart2 rx configuration */
  dma_reset(DMA1_CHANNEL1);
  dma_default_para_init(&dma_init_struct);
  dma_init_struct.buffer_size = usart_buffer_size;
  dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
  dma_init_struct.memory_base_addr = (uint32_t) usart_rx_buffer;
  dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_BYTE;
  dma_init_struct.memory_inc_enable = TRUE;
  dma_init_struct.peripheral_base_addr = (uint32_t) &USART2->dt;
  dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_BYTE;
  dma_init_struct.peripheral_inc_enable = FALSE;
  dma_init_struct.priority = DMA_PRIORITY_MEDIUM;
  dma_init_struct.loop_mode_enable = FALSE;
  dma_init(DMA1_CHANNEL1, &dma_init_struct);
  /* config flexible dma for usart2 tx */
  dma_flexible_config(DMA1, FLEX_CHANNEL1, DMA_FLEXIBLE_UART2_RX);
  dma_channel_enable(DMA1_CHANNEL1, TRUE);
}

void chry_dap_usb2uart_uart_config_callback(struct cdc_line_coding *line_coding)
{
  usart_stop_bit_num_type usart_stop_bit = USART_STOP_1_BIT;
  usart_data_bit_num_type usart_data_bit = USART_DATA_8BITS;
  usart_parity_selection_type usart_parity_select = USART_PARITY_NONE;

  /* stop bit */
  switch (line_coding->bCharFormat)
  {
    case 0x0:
      usart_stop_bit = USART_STOP_1_BIT;
      break;
    /* to be used when transmitting and receiving data in smartcard mode */
    case 0x1:
      usart_stop_bit = USART_STOP_1_5_BIT;
      break;
    case 0x2:
      usart_stop_bit = USART_STOP_2_BIT;
      break;
    default:
      break;
  }
  switch (line_coding->bDataBits)
  {
    /* hardware usart not support data bits for 5/6 */
    case 0x5:
    case 0x6:
    case 0x7:
      break;
    case 0x8:
      usart_data_bit = USART_DATA_8BITS;
      break;
    /* hardware usart not support data bits for 16 */
    case 0x10:
      break;
    default:
      break;
  }
  /* parity */
  switch (line_coding->bParityType)
  {
    case 0x0:
      usart_parity_select = USART_PARITY_NONE;
      break;
    case 0x1:
      usart_parity_select = USART_PARITY_ODD;
      break;
    case 0x2:
      usart_parity_select = USART_PARITY_EVEN;
      break;
    /* hardware usart not support partiy for mark and space */
    case 0x3:
    case 0x4:
      break;
    default:
      break;
  }

  if (usart_parity_select == USART_PARITY_NONE)
  {
    usart_data_bit = USART_DATA_8BITS;
  }
  else
  {
    usart_data_bit = USART_DATA_9BITS;
  }

  usart_init(USART2, line_coding->dwDTERate, usart_data_bit, usart_stop_bit);
  usart_parity_selection_config(USART2, usart_parity_select);
}